﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Timers;
using Quartz;
using Quartz.Impl;
using Quartz.Impl.Triggers;

namespace QuartzExt
{
    /// <summary>
    /// JobResult 消费者
    /// </summary>
    /// <param name=""></param>
    public delegate void JobResultConsumer(JobResult result);
    /// <summary>
    /// 任务管理
    /// </summary>
    public static class QuaztzManager
    {       
        private static StdSchedulerFactory factory = new StdSchedulerFactory();
        internal static ConcurrentQueue<JobResult> MessageQueue { get; set; } = new ConcurrentQueue<JobResult>();
        private static Timer consumerTimer;
        private static JobResultConsumer Consumer;
        private static List<JobTuple> jobTuples = new List<JobTuple>();
        static QuaztzManager()
        {
            consumerTimer = new Timer(1000);
            consumerTimer.AutoReset = true;
            consumerTimer.Elapsed += ConsumerTimer_Elapsed;
            consumerTimer.Start();
        }

        private static void ConsumerTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            JobResult result;
            while (true)
            {               
                if (MessageQueue.TryDequeue(out result))
                {
                    Consumer?.Invoke(result);
                }
                else
                {
                    break;                    
                }
            }             
        }
        /// <summary>
        /// 设置任务结果消费
        /// </summary>
        /// <param name="consumer"></param>
        public static void SetConsumer(JobResultConsumer consumer)
        {
            Consumer = consumer;            
        }
        /// <summary>
        /// 开始任务
        /// </summary>
        /// <param name="jobInfo"></param>
        public static void Start(JobInfo jobInfo)
        {
            var f = jobTuples.Find(p => p.JobInfo.Name == jobInfo.Name && p.JobInfo.Group == jobInfo.Group);
            if (f != null)
            {
                f.Scheduler.PauseAll();
                jobTuples.Remove(f);
            }            
            var jobType = Assembly.LoadFile(jobInfo.AssemblyFile).GetType(jobInfo.JobType);    
            JobBuilder jobBuilder = JobBuilder.Create(jobType).WithIdentity(jobInfo.Name, jobInfo.Group);
            jobBuilder.UsingJobData("AttachParam",jobInfo.AttachParam);          
            IJobDetail jobDetail = jobBuilder.Build();                
            IScheduler sch = factory.GetScheduler().Result;          
            TriggerBuilder triggerBuilder = TriggerBuilder.Create();
            switch (jobInfo.TriggerType)
            {
                case TriggerType.Simple:
                    triggerBuilder.StartNow().WithSimpleSchedule(x => x
                        .WithIntervalInSeconds(jobInfo.Interval)
                        .RepeatForever());
                    break;
                case TriggerType.Cron:
                    triggerBuilder.WithCronSchedule(jobInfo.Cron);                      
                    break;
            }
            ITrigger trigger = triggerBuilder.Build();
            sch.ScheduleJob(jobDetail, trigger);//添加计划者
            sch.Start();
            jobTuples.Add(new JobTuple()
            {
                JobInfo = jobInfo,
                Scheduler = sch
            });
        }
        /// <summary>
        /// 停止任务
        /// </summary>
        /// <param name="group"></param>
        /// <param name="name"></param>
        public static void Pause(string group, string name)
        {
            var f = jobTuples.FirstOrDefault(p=>p.JobInfo.Name == name && p.JobInfo.Group == group);
            f?.Scheduler.PauseAll();
        }
    }
}
